﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Wpf2.Models;
using Wpf2.ViewModels;
using WPFServices;

namespace Wpf2.Views
{
    /// <summary>
    /// Interaction logic for AddInventory.xaml
    /// ps:// ở chức năng lưu sẽ không lưu sản phẩm chưa nhập số lượng, còn in ra thì vẫn cho phép in ra những sản phẩm số lượng = 0
    /// </summary>
    public partial class AddInventory : UserControl
    {
        USER user = new USER() { ID_USER = 0 };
        bool _canExcuteTextChangedEvent = true;
        NotifiableCollection<Catalogs> _catalogs;
        InventoryViewModel addInventoryVM = new InventoryViewModel();
        public ObservableCollection<Products> ObsProducts = new ObservableCollection<Products>();
        public ICommand SaveOrder { get; set; }
        public ICommand PrintOrder { get; set; }
        public decimal TotalPayment = 0;

        public AddInventory()
        {
            try
            {
                InitializeComponent();
                LoadListCatalogIntoListView();
                ObsProducts = addInventoryVM.obsProducts;
                dtgInventory.ItemsSource = addInventoryVM.ListProductsForAddInvetory;
                dtgInventory.RowEditEnding += DtgInventoryRowEditEnding;
                dtgInventory.LoadingRow += dtgInventory_LoadingRow;
                txtUserID.DataContext = user;
                txtTotalPayment.Text = TotalPayment + " VNĐ";
                chkDahoacuong.DataContext = addInventoryVM;
                InitializeCommand();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #region -- define ICommand: SaveOrder ---

        private void InitializeCommand()
        {
            SaveOrder = new RelayCommand<object>
                (
                    CanExcutedSaveOrderCommand,
                    SaveOrderToDataBase
                );
            PrintOrder = new RelayCommand<object>

            (
                CanExcutedPrintCommand,
                ExcutedPrintFunction
            );

            btnSaveAddInvetory.Command = SaveOrder;
            btnSaveAddInvetory.CommandParameter = dtgInventory.ItemsSource;
            btnPrint.Command = PrintOrder;
        }

        private bool CanExcutedPrintCommand(object obj)
        {
            // neu da duoc lưu => đã thỏa các điều kiện
            return addInventoryVM.IsSaved;
        }


        private void ExcutedPrintFunction(object obj)
        {
            var fEditForPrint = new FormEditBeforePrintAddOrder(addInventoryVM.removeAllNullProduct(), TotalPayment, addInventoryVM.IsMarble);
            fEditForPrint.ShowDialog();
        }

        private bool CanExcutedSaveOrderCommand(object obj)
        {
            return !string.IsNullOrEmpty(txtUserID.Text) && WPFServices.Services.UserService.GetUser(user.ID_USER??0) != null && IsExistProduct() && !addInventoryVM.IsSaved;
        }

        public bool IsExistProduct()
        {
            return addInventoryVM.ListProductsForAddInvetory.Any(pro => pro.ProductIdAuto > 0 && pro.InventoryCount > 0);
        }

        public void SaveOrderToDataBase(object o)
        {
            if (addInventoryVM.NumberrOfSaved > 0)
                if (MessageBox.Show("Hóa đơn sẽ được tạo mới. Bạn có muốn tiếp tục lưu hóa đơn?", "Xác Nhận!", MessageBoxButton.YesNo) == MessageBoxResult.No)
                    return;
            var idOfNewOrder = CreateNewOrder();
            foreach (var pro in addInventoryVM.ListProductsForAddInvetory.Where(pro => pro.ProductIdAuto > 0 && pro.InventoryCount > 0))
            {
                if (addInventoryVM.IsMarble)
                    WPFServices.Services.Products.UpdateInvetoryCountByProductID(pro.ProductId, pro.InventoryCount, pro.ProductWidth, pro.ProductHeight);
                else
                    WPFServices.Services.Products.UpdateInvetoryCountByProductID(pro.ProductId, pro.InventoryCount);
                CreateNewOrderDetail(idOfNewOrder, pro.ProductIdAuto, pro.InventoryCount, pro.ProductHeight, pro.ProductWidth, pro.ProductM2);
            }
            addInventoryVM.isSaved();
            MessageBox.Show("Lưu thành công");
        }

        #endregion

        private void dtgInventory_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Header = e.Row.GetIndex() + 1;

        }
        private void LoadListCatalogIntoListView()
        {
            var listCa = WPFServices.Services.Catalogs.GetListCatalogs().Select(x => new Catalogs
                                                                                         {
                                                                                             IDCatalog = x.ID_CATALOG,
                                                                                             CatalogName = x.NAME_CATALOG,
                                                                                             CatalogNotes = x.NOTES_CATALOG
                                                                                         });
            _catalogs = new NotifiableCollection<Catalogs>();
            foreach (var c in listCa)
            {
                _catalogs.Add(c);
            }
            lvCatalog.DataContext = _catalogs;
        }
        private void DtgInventoryRowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
        {
            if (!addInventoryVM.lastProductIsNull())
                addInventoryVM.addProduct(new Products());
        }

        private void ComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _canExcuteTextChangedEvent = false; // when get content's Commbobox to set text's textbox => TextChanged will be excuted => stop event
            var cmbListToChoose = sender as ComboBox;
            if (cmbListToChoose != null)
            {
                var stp = cmbListToChoose.Parent as Grid;
                if (stp != null)
                {
                    var txtProductName = stp.Children[0] as TextBox;
                    var cbItem = (ComboBoxItem)cmbListToChoose.SelectedItem;
                    if (txtProductName != null)
                    {
                        var p = txtProductName.DataContext as Products;

                        var np = WPFServices.Services.Products.GetProduct(int.Parse(cbItem.Tag.ToString()));

                        if (null != cmbListToChoose.SelectedItem)
                        {
                            if (p != null)
                            {
                                p.ProductIdAuto = np.ID_PRO_AUTO;
                                p.ProductName = np.NAME_PRO;
                                p.ProductId = np.ID_PRO;
                                p.ProductDescription = np.DESCRIPTIONS;
                                if (np.DETAILS_PRODUCTS.COST_PRICES != null)
                                    p.CostPrice = (decimal)np.DETAILS_PRODUCTS.COST_PRICES;
                                p.Unit = new Unit { UnitID = np.DETAILS_PRODUCTS.UNIT.ID_UNIT, UnitName = np.DETAILS_PRODUCTS.UNIT.NAME_UNIT, UnitNote = np.DETAILS_PRODUCTS.UNIT.NOTES_UNIT };
                                p.catalog = new Catalogs { CatalogName = np.CATALOG.NAME_CATALOG, CatalogNotes = np.CATALOG.NOTES_CATALOG, IDCatalog = np.CATALOG.ID_CATALOG };
                            }
                        }
                    }
                }
            }
            _canExcuteTextChangedEvent = true;
            if (!addInventoryVM.lastProductIsNull())
                addInventoryVM.addProduct(new Products());
        }

        private void TxtProductNameTextChanged(object sender, TextChangedEventArgs e)
        {
            if (!_canExcuteTextChangedEvent) // specify is event can run or not
                return;
            var txtProductName = sender as TextBox;
            if (txtProductName != null)
            {
                var p = txtProductName.DataContext as Products;
                if (p != null && !string.IsNullOrEmpty(p.ProductName)) // if text's textbox change when exist Product was binded => delete Product and create new Product to find
                {
                    var index = addInventoryVM.ListProductsForAddInvetory.IndexOf(p);
                    addInventoryVM.ListProductsForAddInvetory.RemoveAt(index);
                    addInventoryVM.ListProductsForAddInvetory.Insert(index, new Products());
                    return;
                }
            }
            var stp = new Grid();
            if (txtProductName != null) stp = txtProductName.Parent as Grid;
            if (stp == null) return;
            var cmbListToChoose = stp.Children[1] as ComboBox;
            if (cmbListToChoose == null) return;
            cmbListToChoose.Items.Clear();

            if (txtProductName != null) LoadComboboxItem(ObsProducts, txtProductName.Text, cmbListToChoose);

            cmbListToChoose.IsDropDownOpen = cmbListToChoose.HasItems;
        }

        private void TxtProductNameLostFocus(object sender, RoutedEventArgs e)
        {
            var txtProductName = sender as TextBox;
            if (txtProductName == null) return;
            var stp = txtProductName.Parent as Grid;
            if (stp == null) return;
            var cmbListToChoose = stp.Children[1] as ComboBox;
            if (cmbListToChoose != null) cmbListToChoose.IsDropDownOpen = false;
        }

        private void LoadComboboxItem(ObservableCollection<Products> productList, string searchString, ItemsControl comboboxResult)
        {
            if (productList == null) throw new ArgumentNullException("productList");
            foreach (var item in from item in ObsProducts where !string.IsNullOrEmpty(searchString) where !IsExistInProductList(addInventoryVM.ListProductsForAddInvetory, item) where item.ProductId.StartsWith(searchString, StringComparison.CurrentCultureIgnoreCase) select item)
            {
                var cbItem = new ComboBoxItem {Content = item.ProductId, Tag = item.ProductIdAuto};
                comboboxResult.Items.Add(cbItem);
            }
        }

        private static bool IsExistInProductList(ObservableCollection<Products> productList, Products product)
        {
            try
            {
                return productList.Any(item => item.ProductId == product.ProductId);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return true;
            }
        }

        // just accept numberic is input into textbox
        private void TxtInventoryCountPreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            if (!char.IsDigit(e.Text, e.Text.Length - 1))
            {
                e.Handled = true;
            }
        }

        private static void CreateNewOrderDetail(int iOrderID, int iProductIdAuto, int iInventoryCount, double dHeight, double dWidth, double dM2)
        {
            var newOrderDetail = new ORDER_DETAILS
                                     {
                                         ID_ORD = iOrderID,
                                         ID_PRO_AUTO = iProductIdAuto,
                                         HEIGHT = dHeight,
                                         WIDTH = dWidth,
                                         M2 = dM2,
                                         QUANTITY = iInventoryCount
                                     };
            WPFServices.Services.OrderDetails.CreateOrderDetail(newOrderDetail);
        }

        private int CreateNewOrder()
        {
            try
            {
                var catalogs = lvCatalog.SelectedItem as Catalogs;
                if (catalogs != null)
                {
                    var newOrder = new ORDER
                                       {
                                           ID_CUS = WPFServices.Services.CustomersService.GetOrGreateDefaultCustomer(),// mặc định để xác định là trường hợp nhập kho, cần thêm chức năng kiểm tra => tạo nếu không có
                                           ID_USER = user.ID_USER??0,// phai lay user hien tai
                                           ID_CATALOG = catalogs.IDCatalog, //khong biet lay cai nao??
                                           ORDER_TYPE = 0,// khong hieu la cai j
                                           DATE_ORD = DateTime.Now,
                                           OLD_DEBTS = 0,
                                           PRE_PAID = 0,
                                           TOTAL = TotalPayment,
                                           STATUS_ORD = "0", // vì là hóa đơn nhập nên không có nợ
                                           ORDER_TYPES = addInventoryVM.IsMarble ? 1 : 0
                                       };
                    return WPFServices.Services.Orders.CreateOrder(newOrder);
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
                return 0;
            }
            return 0;
        }


        private void TxtProductNameKeydown(object sender, KeyEventArgs e)
        {
            var txt = sender as TextBox;
            if (txt == null) return;
            var p = txt.DataContext as Products;
            if (e.Key != Key.Enter) return;
            var np = WPFServices.Services.Products.GetProductByID(txt.Text);
            if (np == null) return;
            if (p != null)
            {
                p.ProductIdAuto = np.ID_PRO_AUTO;
                p.ProductName = np.NAME_PRO;
                p.ProductId = np.ID_PRO;
                p.ProductDescription = np.DESCRIPTIONS;
                if (np.DETAILS_PRODUCTS.COST_PRICES != null)
                    p.CostPrice = (decimal)np.DETAILS_PRODUCTS.COST_PRICES;
                p.Unit = new Unit { UnitID = np.DETAILS_PRODUCTS.UNIT.ID_UNIT, UnitName = np.DETAILS_PRODUCTS.UNIT.NAME_UNIT, UnitNote = np.DETAILS_PRODUCTS.UNIT.NOTES_UNIT };
                p.catalog = new Catalogs { CatalogName = np.CATALOG.NAME_CATALOG, CatalogNotes = np.CATALOG.NOTES_CATALOG, IDCatalog = np.CATALOG.ID_CATALOG };
            }
            if (!addInventoryVM.lastProductIsNull())
                addInventoryVM.addProduct(new Products());
        }

        private void TxtInventoryTextChanged(object sender, TextChangedEventArgs e)
        {
            CaculationPaymentForAllProduct();
        }

        private void CaculationPaymentForAllProduct()
        {
            TotalPayment = 0;
            foreach (var pro in addInventoryVM.ListProductsForAddInvetory.Where(pro => !string.IsNullOrEmpty(pro.ProductId)))
                TotalPayment += pro.TotalInPayment;
            txtTotalPayment.Text = TotalPayment + " VNĐ";
        }

        
        /// <summary>
        /// Hàm sử dụng khi có thay đổi về dài rộng. Mục đích tính toán payment
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CaculationPayment(object sender, RoutedEventArgs e)
        {
            CaculationPaymentForAllProduct();
        }


    }
}
